# -*- coding: utf-8 -*-
# Description: 读iot数据 需要传path tag (nowtime)/(starttime endtime)
# Created: zxj 2023/12/8
import time
from datetime import datetime

import numpy as np
import pandas as pd
import requests


class GetIotData:
    # 常量
    API_URL_TIME_BEFORE = "http://eplat.baogang.info/service/D_A_IOTDB_READ_DATA_0007"  # 向前获取时间戳
    API_URL_TIME_AFTER = "http://eplat.baogang.info/service/D_A_IOTDB_READ_DATA_0008"  # 向后获取时间戳
    API_URL_TIME_RANGE = "http://eplat.baogang.info/service/D_A_IOTDB_READ_DATA_0001"  # 按时间范围获取数据（信号/模拟量）
    API_URL_TIME_NEWEST = "http://eplat.baogang.info/service/D_A_IOTDB_READ_DATA_0003"  # 取最新的值
    API_URL_VALUE_INSERT = "http://eplat.baogang.info/service/D_A_IOTDB_READ_DATA_0006"  # 插入数据
    CLIENT_ID = "iedas-line18d5120ykI6o374Xr"
    CLIENT_SECRET = "0A9883E2EC88652C44F403823BADD205"

    # 获取信号数据时，先获取信号的开始时间和结束时间(19位时间戳)，注意path末尾要加".I"
    # 返回列表
    @staticmethod
    def get_signal_info(path, now_time, flag):
        if flag == 0:
            url = GetIotData.API_URL_TIME_BEFORE
        else:
            url = GetIotData.API_URL_TIME_AFTER

        params = {
            "clientId": GetIotData.CLIENT_ID,
            "clientSecret": GetIotData.CLIENT_SECRET,
            "params": {
                "path": path + ".I",
                "queryTime": now_time
            },
            "showCount": "false",
            "isEnableLimit": "false"
        }

        response = requests.post(url, json=params)
        run_status = False
        msg = ""
        rst = []

        if response.status_code == 200:
            api_data = response.json()
            if len(api_data['__blocks__']) == 0:
                msg = '0007_0008_api:blocks返回异常！'
                return run_status, msg, rst
            else:
                result_I = api_data['__blocks__']['result']['rows']
                if len(result_I) > 0:
                    run_status = True
                    rst = result_I[0]  # 列表，按顺序分别是：开始时间戳、Hz、结束时间戳、cl
                else:
                    msg = "0007_0008_api:无数据！"
        else:
            msg = f'0007_0008_api_Error: {response.status_code} - {response.text}'
        return run_status, msg, rst

    # 获取时间范围内的数据(包括信号数据+单值数据，区别在于信号数据path末尾要加".S" 以及 tag="Value")
    # 返回列表
    @staticmethod
    def get_value_time_range(path, tag, start_time, end_time, if_signal=False):
        if if_signal:
            path_new = path + ".S"
        else:
            path_new = path
        params = {
            "clientId": GetIotData.CLIENT_ID,
            "clientSecret": GetIotData.CLIENT_SECRET,
            "params": {
                "path": path_new,
                "tag": tag,
                "start_time": str(start_time),
                "end_time": str(end_time)
            },
            "showCount": "false",
            "isEnableLimit": "false"
        }

        response = requests.post(GetIotData.API_URL_TIME_RANGE, json=params)
        run_status = False
        msg = ""
        rst = []

        if response.status_code == 200:
            api_data = response.json()
            result_S = api_data['__blocks__']['result']['rows']  # 列表，按顺序分别是：开始时间戳、Hz、结束时间戳、cl
            if len(result_S) > 0:
                run_status = True
                rst = result_S
            else:
                msg = "0001_api:无数据！"
        else:
            msg = f'0001_Error: {response.status_code} - {response.text}'
        return run_status, msg, rst

    # 获取信号数据，返回run_status, msg, rst，分别为运行状态，报错信息，结果(dict格式，包括 hz cl datetime value_list)
    @staticmethod
    def get_iot_signal(path, now_time, flag=0):
        if_res1, msg1, info_list1 = GetIotData.get_signal_info(path, now_time, flag)
        run_status = False
        rst = {}
        if if_res1:
            if_res2, msg2, info_list2 = GetIotData.get_value_time_range(path, "Value", info_list1[0], info_list1[2], True)
            if if_res2:
                run_status = True
                msg = "信号数据查询成功!"
                time0 = pd.to_datetime(int(info_list1[0]) / 10 ** 6 + 28800000, unit='ms')
                time0_str = time0.strftime('%Y-%m-%d %H:%M:%S.%f')
                values = list(map(lambda x: float(x[1]), info_list2))
                rst = {
                    'hz': int(info_list1[1]),
                    'cl': int(info_list1[3]),
                    'datetime': time0_str,
                    'values': values
                }
            else:
                msg = msg2
        else:
            msg = msg1
        return run_status, msg, rst

    # 获取模拟量数据，返回run_status, msg, rst，分别为运行状态，报错信息，结果(dataframe格式，包括 timestamp value datetime)
    @staticmethod
    def get_iot_value(path, tag, start_time, end_time):
        run_status = False
        if_res, msg0, info_list = GetIotData.get_value_time_range(path, tag, start_time, end_time, False)
        if if_res:
            run_status = True
            msg = "模拟数据查询成功!"
            rst = pd.DataFrame(info_list, columns=['timestamp', 'value'])
            rst['value'] = rst['value'].astype(float)
            rst['timestamp'] = pd.to_numeric(rst['timestamp'], errors='coerce')
            rst['datetime'] = pd.to_datetime(rst['timestamp'] / 10 ** 6 + 28800000, unit='ms')
        else:
            msg = msg0
            rst = pd.DataFrame()
        return run_status, msg, rst

    # 数据插入iot：报警模型 特征值+结果值
    @staticmethod
    def insert_iot_value(path, tag, values):
        sql = f"""INSERT INTO {path} (timestamp, {tag}) VALUES {values}"""
        # print(sql)
        url = GetIotData.API_URL_VALUE_INSERT

        params = {
            "clientId": GetIotData.CLIENT_ID,
            "clientSecret": GetIotData.CLIENT_SECRET,
            "sql": sql,
            "showCount": "false",
            "isEnableLimit": "false"
        }

        response = requests.post(url, json=params)
        api_data = response.json()
        api_status = api_data['__sys__']['status']

        if api_status == 0:
            run_status = True
            msg = "数据更新成功!"
        elif api_status == 1:
            run_status = True
            msg = "数据插入成功!"
        else:
            run_status = False
            msg = f"0006_api_Error: {api_data['__sys__']['msg']}"
        return run_status, msg

    # 获取模型量最新数据
    @staticmethod
    def get_iot_value_newest(path, tag):
        params = {
            "clientId": GetIotData.CLIENT_ID,
            "clientSecret": GetIotData.CLIENT_SECRET,
            "params": {
                "path": path,
                "tag": tag
            },
            "showCount": "false",
            "isEnableLimit": "false"
        }

        response = requests.post(GetIotData.API_URL_TIME_NEWEST, json=params)
        run_status = False
        rst = {}

        if response.status_code == 200:
            api_data = response.json()
            result = api_data['__blocks__']['result']['rows']  # 列表，按顺序分别是：开始时间戳、Hz、结束时间戳、cl
            if len(result) > 0:
                data = result[0]
                run_status = True
                msg = "最新模拟数据查询成功!"
                rst['value'] = float(data[2])
                rst['timestamp'] = int(data[0])
                time0 = pd.to_datetime(int(data[0]) / 10 ** 6 + 28800000, unit='ms')
                rst['datetime'] = time0.strftime('%Y-%m-%d %H:%M:%S.%f')
            else:
                msg = "0003_api:无数据！"
        else:
            msg = f'0003_Error: {response.status_code} - {response.text}'
        return run_status, msg, rst

    # 获取模拟量n小时内最新数据
    @staticmethod
    def get_iot_value_newest_nhs(path, tag, now_time, n=2):
        start_time = now_time - n * 60 * 60 * 10 ** 9
        run_status = False
        rst = {}
        if_res, msg0, info_list = GetIotData.get_value_time_range(path, tag, start_time, now_time, False)
        if if_res:
            run_status = True
            msg = f"模拟量{n}小时内最新数据查询成功!"
            last_row = info_list[-1]
            rst['value'] = float(last_row[1])
            rst['timestamp'] = int(last_row[0])
            time0 = pd.to_datetime(int(last_row[0]) / 10 ** 6 + 28800000, unit='ms')
            rst['datetime'] = time0.strftime('%Y-%m-%d %H:%M:%S.%f')
        else:
            msg = msg0
        return run_status, msg, rst

    # 获取波形n小时内最新数据
    @staticmethod
    def get_iot_signal_newest_nhs(path, now_time, n=2, flag=0):
        if_res1, msg1, info_list1 = GetIotData.get_signal_info(path, now_time, flag)
        run_status = False
        rst = {}
        if if_res1:
            now_time_dt = datetime.strptime(now_time, "%Y/%m/%d %H:%M:%S.%f") if '/' in now_time else datetime.strptime(now_time, "%Y-%m-%d %H:%M:%S.%f")
            now_time_timestamp = int(now_time_dt.timestamp()) * 10 ** 3
            compare_time = now_time_timestamp - n * 60 * 60 * 10 ** 9 if flag == 0 else now_time_timestamp + n * 60 * 60 * 10 ** 9
            if (flag == 0 and int(info_list1[2]) < compare_time) or (flag == 1 and int(info_list1[0]) > compare_time):
                msg = f"波形{n}小时内无数据!"
            else:
                if_res2, msg2, info_list2 = GetIotData.get_value_time_range(path, "Value", info_list1[0], info_list1[2], True)
                if if_res2:
                    run_status = True
                    msg = f"波形{n}小时内最新数据查询成功!"
                    time0 = pd.to_datetime(int(info_list1[0]) / 10 ** 6 + 28800000, unit='ms')
                    time0_str = time0.strftime('%Y-%m-%d %H:%M:%S.%f')
                    values = list(map(lambda x: float(x[1]), info_list2))
                    rst = {
                        'hz': int(info_list1[1]),
                        'cl': int(info_list1[3]),
                        'datetime': time0_str,
                        'values': values,
                        'start_time': info_list1[0]
                    }
                else:
                    msg = msg2
        else:
            msg = msg1
        return run_status, msg, rst


if __name__ == '__main__':
    log_time1 = time.time()

    # 读取信号数据
    # path = "root.BGTA.BGTAIOAA00.IDL4_MF_GWS_01.clN"
    # now_time = "2023/12/21 14:42:41.560"
    # run_status, msg, rst = GetIotData.get_iot_signal(path, now_time, 0)

    # 读取模拟量数据
    # path = "root.BGTA.BGTAISSB00.AD_DMM_01.PLC"  # root.BGTA.BGTAIOAD00.AD_DMM_01.PLC
    # tag = "2050_FMC_COMFU_MRG_F1_MOT1_ArmatureTemp_Act_310514E01_features"  # 2050_FMC_COMFU_MRG_F6_MOT2_ArmatureTemp_Act
    # end_time = (int(time.time()) - 5 * 60) * 10 ** 9
    # start_time = (int(time.time()) - 35 * 60) * 10 ** 9
    # run_status, msg, rst = GetIotData.get_iot_value(path, tag, start_time, end_time)

    # 读取模拟量最新的数据值
    # iot_tag = "root.BGTA.BGTAIOBC00.EMFN_GWV_01.SNR.R00500.C01.V_VV_VEL"
    # split_path_tag = iot_tag.rsplit('.', 1)
    # path = split_path_tag[0]
    # tag = split_path_tag[1]
    # run_status, msg, rst = GetIotData.get_iot_value_newest(path, tag)

    # 读取模拟量2小时内最新的数据值
    iot_tag = "root.BGTA.BGTAIOBC00.EMFN_GWV_01.SNR.R00500.C01.V_VV_VEL"
    split_path_tag = iot_tag.rsplit('.', 1)
    path = split_path_tag[0]
    tag = split_path_tag[1]
    now_time = int(time.time()) * 10 ** 9
    run_status, msg, rst = GetIotData.get_iot_value_newest_nhs(path, tag, now_time)

    # 读取波形2小时内最新的数据
    path = "root.BGTA.BGTAIOAA00.AA_GWS_01.SNR.A00008.C01.V_QW_VEL"
    now_time = "2024/01/22 16:11:00.000"
    run_status, msg, rst = GetIotData.get_iot_signal_newest_nhs(path, now_time)

    # print(run_status, msg, len(rst))
    log_time2 = time.time()
    # print(f"用时：{log_time2-log_time1}s")
